package dancrawler.server;

import dancrawler.proto.cmd.CmdRegister;
import dancrawler.proto.cmd.Command;
import dancrawler.proto.cmd.NetCommand;
import java.nio.ByteBuffer;

/**
 *
 */
public class ProtocolParser {

    private CmdRegister cmdreg = new CmdRegister();

    public ProtocolParser() {
    }

    private NetCommand lookupCmd(short cmd) {
        return cmdreg.getCmd(cmd);
    }

    public void processData(ByteBuffer buff, Connection con) {
        byte[] bytes = buff.array();
        int rem = buff.remaining();
        buff.position(buff.limit());
        processData(bytes, con, rem);
    }

    public void processData(byte[] buff, Connection con, int size) {
        netMsg msg = con.peekMsg();
        NetCommand cmd = null;



        int ix = 0;
        while (ix < size) {
            if (msg == null || msg.isFinalized()) {
                msg = new netMsg((short) 0, (short) 0, con);
                con.addMsg(msg);
            }
            if (msg.getArg() == -1) {
                if (msg.getIndex() == 0) {
                    msg.setCmd((short) ((buff[ix++] & 0xFF) << 8));
                    msg.setIndex(msg.getIndex() + 1);
                    continue;
                } else {
                    msg.setCmd((short) (msg.getCmd() | (buff[ix++] & 0xFF)));
                    msg.setIndex(0);
                    msg.setArg(0);
                    cmd = lookupCmd(msg.getCmd());
                    if (cmd == null) {
                        con.removeMsg(msg);
                        return;
                    }
                    if (cmd.getNumArgs() > 0) {
                        byte[][] bs = new byte[cmd.getNumArgs()][];
                        msg.setArgs(bs);
                    }
                    if (msg.getArg() == cmd.getNumArgs() && msg.getIndex() == cmd.getArgSize(msg.getArg() - 1)) {
                        msg.setFinalized(true);
                        continue;
                    }
                    continue;
                }
            }
            cmd = lookupCmd(msg.getCmd());
            if (cmd == null) {
                con.removeMsg(msg);
                return;
            }
            if (msg.getArg() >= 0) {
                if (msg.getArgs()[msg.getArg()] == null) {
                    if (cmd.getArgSize(msg.getArg()) == -1) {
                        int sz = buff[ix++] & 0xFF;
                        
                        msg.getArgs()[msg.getArg()] = new byte[(int) (sz)];
                    } else {
                        msg.getArgs()[msg.getArg()] = new byte[cmd.getArgSize(msg.getArg())];
                    }
                } else if(msg.getArgs()[msg.getArg()].length != 0) {
                    int t = size - ix;
                    if (msg.getArgs()[msg.getArg()].length - msg.getIndex() > size - ix) {
                        System.arraycopy(buff, ix, msg.getArgs()[msg.getArg()], msg.getIndex(), size - ix);
                        ix += (size - ix);
                    } else {
                        System.arraycopy(buff, ix, msg.getArgs()[msg.getArg()], msg.getIndex(), msg.getArgs()[msg.getArg()].length - msg.getIndex());
                        ix += msg.getArgs()[msg.getArg()].length - msg.getIndex();
                    }
                    msg.setIndex(msg.getIndex() + (t - (size - ix)));

                }
                if (msg.getIndex() == msg.getArgs()[msg.getArg()].length) {
                    msg.setArg(msg.getArg() + 1);
                    msg.setIndex(0);
                    if (msg.getArg() == cmd.getNumArgs()) {
                        msg.setFinalized(true);
                    }
                }
            }
            
        }

    }

    public void writeMsg(ByteBuffer buff, netMsg msg) {
        buff.putShort(msg.getCmd());
        NetCommand com= cmdreg.getCmd(msg.getCmd());
        if (msg.getArgs() != null) {
            for (int i = 0; i < msg.getArgs().length; i++) {
                if (msg.getArgs()[i] != null) {
                    if(com.getArgSize(i) == -1)
                    {
                        byte b = (byte)((msg.getArgs()[i].length) & 0xFF);
                        buff.put(b);
                    }
                    buff.put(msg.getArgs()[i]);
                }
            }
        }
    }

    public void exeMsg(netMsg msg) {
    }
}
